package com.tsmti.util;

import com.baomidou.mybatisplus.toolkit.CollectionUtils;
import com.tsmti.core.util.MapUtils;
import com.tsmti.core.util.StringUtils;
import com.tsmti.system.entity.MessageProperty;
import com.tsmti.system.service.MessagePropertyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Package：com.tsmti.util
 * @Class：CustomMessageResource
 * @Description： 国际化标签
 * @Author：zcw
 * @Date：Created in 2018/5/30 16:21
 * @Company:
 * @Version：
 * @Modified By:
 */
public class MessageResource extends AbstractMessageSource implements ResourceLoaderAware {

   @Autowired
    private  MessagePropertyService messagePropertyService;

    private static Logger logger = LoggerFactory.getLogger(MessageResource.class);

    /**cache resource*/
    private static final Map<String, Map<String, String>> LOCAL_CACHE = new ConcurrentHashMap<>(256);

    /**default base name*/
    private static final String DEFAULT_RESOURCE_BUND_BASE_NAME = "messages";

    @SuppressWarnings("unused")
    private ResourceLoader resourceLoader;

    @PostConstruct
    public void init() {
        this.reload();
    }
    public  void reload() {
        //clear cache while reload data.
        LOCAL_CACHE.clear();
        LOCAL_CACHE.putAll(getAllMessageResource());
    }
    public  Map<String, Map<String, String>> getAllMessageResource() {
        List<MessageProperty> messageI18NPropertyList = messagePropertyService.list();
        if (CollectionUtils.isEmpty(messageI18NPropertyList)) {
            return MapUtils.EMPTY_MAP;
        }
        final Map<String, Map<String, String>> messageResources = new HashMap<>(16);
        final Map<String, String> zhCnMessageResources = new HashMap<>(messageI18NPropertyList.size());
        final Map<String, String> enUsMessageResources = new HashMap<>(messageI18NPropertyList.size());

        for (MessageProperty message : messageI18NPropertyList) {
            String locale = message.getLocale();
            if ("en".equals(locale)) {
                enUsMessageResources.put(message.getCode(), message.getLabelName());
            } else if ("zh".equals(locale)) {
                zhCnMessageResources.put(message.getCode(), message.getLabelName());
            }
        }

        //put into local cache
        LOCAL_CACHE.put(Locale.ENGLISH.getLanguage(), enUsMessageResources);
        LOCAL_CACHE.put(Locale.CHINESE.getLanguage(), zhCnMessageResources);

        return messageResources;
    }
    @Override
    protected String resolveCodeWithoutArguments(String code, Locale locale) {
        return checkFromCachedOrBundResource(code, locale);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = (resourceLoader == null ? new DefaultResourceLoader() : resourceLoader);
    }
    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        //first check from local cache, is none exists. then query from parent message resource which load from bundle resrouces
        String msg = "";
        if(!StringUtils.isEmpty(code)){
            msg = checkFromCachedOrBundResource(code, locale);
        }
        MessageFormat messageFormat = new MessageFormat(msg, locale);
        return messageFormat;
    }

    private String checkFromCachedOrBundResource(String code, Locale locale) {
        String language = locale.getLanguage();
        Map<String, String> props = LOCAL_CACHE.get(language);
        if (null != props && props.containsKey(code)) {
            return props.get(code);
        } else {
            //check from parent message resource. and catch no such element exception.
            try {
                if (null != this.getParentMessageSource()) {
                    return this.getParentMessageSource().getMessage(code, null, locale);
                }
            } catch (Exception ex) {
                logger.error("获取标签名称失败==>"+ code);
            }
            return code;
        }
    }
}
